package com.dmz.proxy.controller;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.dmz.proxy.util.SecurityValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 *
 * @author lee
 */
@Controller
@RequestMapping("${target.mapping}")
@Slf4j
public class ForwardController {

    @Value("${target.url}")
    private String targetUrl;

    @Value("${target.mapping}")
    private String mapping;
    
    private final SecurityValidator securityValidator;
    
    public ForwardController(SecurityValidator securityValidator) {
        this.securityValidator = securityValidator;
    }

    // 所有GET请求处理方法
    @GetMapping(value = {"/system/acct/**", "/system/account2/**", "/system/history/**", "/system/today/**", "/captchaImage", "/getInfo", "/getRouters"})
    public ResponseEntity<String> forwardGetDataRequest(HttpServletRequest request) {
        try {
            // 安全验证
            String servletPath = request.getServletPath();
            if (!securityValidator.isValidPath(servletPath)) {
                log.warn("Invalid path detected: {}", servletPath);
                return createErrorResponse("Invalid request path", HttpStatus.BAD_REQUEST);
            }
            
            String url = getUrl(servletPath);
            if (!securityValidator.isValidUrl(url)) {
                log.warn("Invalid URL generated: {}", url);
                return createErrorResponse("Invalid target URL", HttpStatus.BAD_REQUEST);
            }
            
            log.info("Forwarding GET request to: {}", url);
            
            // 执行请求
            HttpResponse response = HttpUtil.createGet(url).execute();
            
            // 安全处理响应
            return handleHttpResponse(request, response);
            
        } catch (Exception e) {
            log.error("Error forwarding GET request", e);
            return createErrorResponse("Internal server error", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    // POST请求处理方法
    @PostMapping(value = {"/system/account2", "/login", "/logout"})
    public ResponseEntity<String> forwardPostDataRequest(
            @RequestBody(required = false) String requestBody,
            HttpServletRequest request) {
        
        try {
            // 安全验证
            String servletPath = request.getServletPath();
            if (!securityValidator.isValidPath(servletPath)) {
                return createErrorResponse("Invalid request path", HttpStatus.BAD_REQUEST);
            }
            
            // 验证请求体大小
            if (!securityValidator.isValidBodySize(requestBody)) {
                return createErrorResponse("Request body too large", HttpStatus.BAD_REQUEST);
            }
            
            String url = getUrl(servletPath);
            if (!securityValidator.isValidUrl(url)) {
                return createErrorResponse("Invalid target URL", HttpStatus.BAD_REQUEST);
            }
            
            log.info("Forwarding POST request to: {}", url);
            
            // 执行请求
            HttpResponse response = HttpUtil.createPost(url)
                    .body(requestBody)
                    .execute();
            
            // 安全处理响应
            return handleHttpResponse(request, response);
            
        } catch (Exception e) {
            log.error("Error forwarding POST request", e);
            return createErrorResponse("Internal server error", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    // PUT请求处理方法
    @PutMapping(value = {"/system/account2"})
    public ResponseEntity<String> forwardPutDataRequest(
            @RequestBody(required = false) String requestBody,
            HttpServletRequest request) {
        
        try {
            // 安全验证
            String servletPath = request.getServletPath();
            if (!securityValidator.isValidPath(servletPath)) {
                return createErrorResponse("Invalid request path", HttpStatus.BAD_REQUEST);
            }
            
            // 验证请求体大小
            if (!securityValidator.isValidBodySize(requestBody)) {
                return createErrorResponse("Request body too large", HttpStatus.BAD_REQUEST);
            }
            
            String url = getUrl(servletPath);
            if (!securityValidator.isValidUrl(url)) {
                return createErrorResponse("Invalid target URL", HttpStatus.BAD_REQUEST);
            }
            
            log.info("Forwarding PUT request to: {}", url);
            
            // 执行请求
            cn.hutool.http.HttpRequest httpRequest = HttpUtil.createRequest(Method.PUT, url);
            httpRequest.body(requestBody);
            HttpResponse response = httpRequest.execute();
            
            // 安全处理响应
            return handleHttpResponse(request, response);
            
        } catch (Exception e) {
            log.error("Error forwarding PUT request", e);
            return createErrorResponse("Internal server error", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    // DELETE请求处理方法
    @DeleteMapping(value = {"/system/account2/**"})
    public ResponseEntity<String> forwardDeleteDataRequest(
            @RequestBody(required = false) String requestBody,
            HttpServletRequest request) {

        try {
            // 安全验证
            String servletPath = request.getServletPath();
            if (!securityValidator.isValidPath(servletPath)) {
                return createErrorResponse("Invalid request path", HttpStatus.BAD_REQUEST);
            }
            
            // 验证请求体大小
            if (!securityValidator.isValidBodySize(requestBody)) {
                return createErrorResponse("Request body too large", HttpStatus.BAD_REQUEST);
            }
            
            String url = getUrl(servletPath);
            if (!securityValidator.isValidUrl(url)) {
                return createErrorResponse("Invalid target URL", HttpStatus.BAD_REQUEST);
            }
            
            log.info("Forwarding DELETE request to: {}", url);
            
            // 执行请求
            cn.hutool.http.HttpRequest httpRequest = HttpUtil.createRequest(Method.DELETE, url);
            httpRequest.body(requestBody);
            HttpResponse response = httpRequest.execute();
            
            // 安全处理响应
            return handleHttpResponse(request, response);
            
        } catch (Exception e) {
            log.error("Error forwarding DELETE request", e);
            return createErrorResponse("Internal server error", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    // 流式POST请求处理方法
    @PostMapping(value = {"/system/*/export", "/system/*/exportTxt"})
    public ResponseEntity<StreamingResponseBody> forwardStreamingPostRequest(
            @RequestBody(required = false) String requestBody,
            HttpServletRequest request) {

        try {
            // 安全验证
            String servletPath = request.getServletPath();
            if (!securityValidator.isValidPath(servletPath)) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }
            
            // 验证请求体大小
            if (!securityValidator.isValidBodySize(requestBody)) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }
            
            String url = getUrl(servletPath);
            if (!securityValidator.isValidUrl(url)) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }
            
            log.info("Forwarding streaming POST request to: {}", url);
            
            // 执行请求
            HttpResponse response = HttpUtil.createPost(url)
                    .body(requestBody)
                    .execute();
            
            // 检查内容类型
            String contentType = response.header("Content-Type");
            if (!securityValidator.isSafeContentType(contentType)) {
                log.warn("Unsafe content type in streaming response: {}", contentType);
                return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).build();
            }
            
            final byte[] responseData = response.bodyBytes();
            
            StreamingResponseBody streamingBody = outputStream -> {
                try {
                    outputStream.write(responseData);
                    outputStream.flush();
                } catch (Exception e) {
                    log.error("Error writing streaming response", e);
                }
            };
            
            // 设置安全头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType(contentType));
            headers.set("X-Content-Type-Options", "nosniff");
            headers.set("X-XSS-Protection", "1; mode=block");
            
            return new ResponseEntity<>(streamingBody, headers, HttpStatus.OK);
            
        } catch (Exception e) {
            log.error("Error forwarding streaming request", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 统一处理HTTP响应
     */
    private ResponseEntity<String> handleHttpResponse(HttpServletRequest request,HttpResponse response) {
        try {
            String contentType = response.header("Content-Type");
            
            // 检查内容类型是否安全
            if (!securityValidator.isSafeContentType(contentType)) {
                log.warn("Unsafe content type: {}", contentType);
                return createErrorResponse("Unsupported content type", HttpStatus.UNSUPPORTED_MEDIA_TYPE);
            }
            
            String responseBody = response.body();
            int statusCode = response.getStatus();
            
            // 对文本内容进行安全处理
            if (contentType != null && contentType.contains("text") || contentType.contains("json") || contentType.contains("xml")) {
                responseBody = securityValidator.sanitizeJsonResponse(responseBody);
                responseBody = securityValidator.escapeHtml(responseBody);
            }
            
            // 设置安全头
            HttpHeaders headers = new HttpHeaders();
            if (contentType != null) {
                headers.setContentType(MediaType.parseMediaType(contentType));
            }
            headers.set("X-Content-Type-Options", "nosniff");
            headers.set("X-XSS-Protection", "1; mode=block");
            headers.set("Content-Security-Policy", "default-src 'self'");

     /*       try{
                String author = request.getParameter("author");
                author = URLEncoder.encode(author, "UTF-8");
                Cookie cookie = new Cookie("author", author);
                cookie.setHttpOnly(true);
                cookie.setMaxAge(10000);
                headers.set("cookie", cookie.getValue());
            }catch (Exception e){
                log.error("Error setting cookie", e);
            }*/
            
            return new ResponseEntity<>(responseBody, headers, HttpStatus.valueOf(statusCode));
            
        } catch (Exception e) {
            log.error("Error handling HTTP response", e);
            return createErrorResponse("Error processing response", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    /**
     * 创建错误响应
     */
    private ResponseEntity<String> createErrorResponse(String message, HttpStatus status) {
        String safeMessage = securityValidator.escapeHtml(message);
        String jsonResponse = String.format("{\"error\":\"%s\",\"status\":%d}", safeMessage, status.value());
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Content-Type-Options", "nosniff");
        
        return new ResponseEntity<>(jsonResponse, headers, status);
    }

    /**
     * 构建目标URL（保持不变）
     */
    private String getUrl(String url) {
        return targetUrl + (url.startsWith("/dev-api") ? url.replace(mapping, "") : url);
    }
}